#include "DXUT.h"
#include "Collision.h"

bool collision(IWorld * world, const D3DXVECTOR3 *obb, Block *blocks, INTVECTOR3 * pos, bool *collides) {
	bool result = false;
	for (int i = 0; i < 8; i++) {
		pos[i]			= INTVECTOR3(obb[i]);
		blocks[i]		= world->getBlock(pos[i].x, pos[i].z, pos[i].y);
		collides[i]		= (blocks[i].blockID != AIR);
		result |= collides[i];
	}
	return result;
};

bool collision(IWorld * world, const D3DXAABB &aabb, Block *blocks, INTVECTOR3 * pos, bool *collides) {
	bool result = false;
	int Minx = static_cast<int>(floor(aabb.Min.x + 0.5f)); 
	int Miny = static_cast<int>(floor(aabb.Min.y + 0.5f)); 
	int Minz = static_cast<int>(floor(aabb.Min.z + 0.5f)); 
	int Maxx = static_cast<int>(floor(aabb.Max.x + 0.5f)); 
	int Maxy = static_cast<int>(floor(aabb.Max.y + 0.5f)); 
	int Maxz = static_cast<int>(floor(aabb.Max.z + 0.5f)); 

	blocks[0]		= world->getBlock(Minx, Minz, Miny);
	pos[0]			= INTVECTOR3(Minx, Minz, Miny);
	collides[0]		= (blocks[0].blockID != AIR);
	result |= collides[0];

	blocks[1]		= world->getBlock(Minx, Minz, Maxy);
	pos[1]			= INTVECTOR3(Minx, Minz, Maxy);
	collides[1]		= (blocks[1].blockID != AIR);
	result |= collides[1];

	blocks[2]		= world->getBlock(Minx, Maxz, Miny);
	pos[2]			= INTVECTOR3(Minx, Maxz, Miny);
	collides[2]		= (blocks[2].blockID != AIR);
	result |= collides[2];

	blocks[3]		= world->getBlock(Minx, Maxz, Maxy);
	pos[3]			= INTVECTOR3(Minx, Maxz, Maxy);
	collides[3]		= (blocks[3].blockID != AIR);
	result |= collides[3];

	blocks[4]		= world->getBlock(Maxx, Minz, Miny);
	pos[4]			= INTVECTOR3(Maxx, Minz, Miny);;
	collides[4]		= (blocks[4].blockID != AIR);
	result |= collides[4];

	blocks[5]		= world->getBlock(Maxx, Minz, Maxy);
	pos[5]			= INTVECTOR3(Maxx, Minz, Maxy);
	collides[5]		= (blocks[5].blockID != AIR);
	result |= collides[5];

	blocks[6]		= world->getBlock(Maxx, Maxz, Miny);
	pos[6]			= INTVECTOR3(Maxx, Maxz, Miny);;
	collides[6]		= (blocks[6].blockID != AIR);
	result |= collides[6];

	blocks[7]		= world->getBlock(Maxx, Maxz, Maxy);
	pos[7]			= INTVECTOR3(Maxx, Maxz, Maxy);
	collides[7]		= (blocks[7].blockID != AIR);
	result |= collides[7];

	return result;
};

int axisAlignedCollision(const D3DXAABB &staticbox, const D3DXAABB &movingbox, const D3DXVECTOR3 &speed, float d, float &dtime)
{
	float xsize = (staticbox.Max.x - staticbox.Min.x);
	float ysize = (staticbox.Max.y - staticbox.Min.y);
	float zsize = (staticbox.Max.z - staticbox.Min.z);

	D3DXAABB relbox(
		D3DXVECTOR3(movingbox.Min.x - staticbox.Min.x,
		movingbox.Min.y - staticbox.Min.y,
		movingbox.Min.z - staticbox.Min.z),
		D3DXVECTOR3(movingbox.Max.x - staticbox.Min.x,
		movingbox.Max.y - staticbox.Min.y,
		movingbox.Max.z - staticbox.Min.z)
		);

	if(speed.x > 0) // Check for collision with X- plane
	{
		if(relbox.Max.x <= d)
		{
			dtime = - relbox.Max.x / speed.x;
			if((relbox.Min.y + speed.y * dtime < ysize) &&
					(relbox.Max.y + speed.y * dtime > 0) &&
					(relbox.Min.z + speed.z * dtime < zsize) &&
					(relbox.Max.z + speed.z * dtime > 0))
				return 0;
		}
		else if(relbox.Min.x > xsize)
		{
			return -1;
		}
	}
	else if(speed.x < 0) // Check for collision with x+ plane
	{
		if(relbox.Min.x >= xsize - d)
		{
			dtime = (xsize - relbox.Min.x) / speed.x;
			if((relbox.Min.y + speed.y * dtime < ysize) &&
					(relbox.Max.y + speed.y * dtime > 0) &&
					(relbox.Min.z + speed.z * dtime < zsize) &&
					(relbox.Max.z + speed.z * dtime > 0))
				return 0;
		}
		else if(relbox.Max.x < 0)
		{
			return -1;
		}
	}

	// NO else if here

	if(speed.y > 0) // Check for collision with y- plane
	{
		if(relbox.Max.y <= d)
		{
			dtime = - relbox.Max.y / speed.y;
			if((relbox.Min.x + speed.x * dtime < xsize) &&
					(relbox.Max.x + speed.x * dtime > 0) &&
					(relbox.Min.z + speed.z * dtime < zsize) &&
					(relbox.Max.z + speed.z * dtime > 0))
				return 1;
		}
		else if(relbox.Min.y > ysize)
		{
			return -1;
		}
	}
	else if(speed.y < 0) // Check for collision with y+ plane
	{
		if(relbox.Min.y >= ysize - d)
		{
			dtime = (ysize - relbox.Min.y) / speed.y;
			if((relbox.Min.x + speed.x * dtime < xsize) &&
					(relbox.Max.x + speed.x * dtime > 0) &&
					(relbox.Min.z + speed.z * dtime < zsize) &&
					(relbox.Max.z + speed.z * dtime > 0))
				return 1;
		}
		else if(relbox.Max.y < 0)
		{
			return -1;
		}
	}

	// NO else if here

	if(speed.z > 0) // Check for collision with z- plane
	{
		if(relbox.Max.z <= d)
		{
			dtime = - relbox.Max.z / speed.z;
			if((relbox.Min.x + speed.x * dtime < xsize) &&
					(relbox.Max.x + speed.x * dtime > 0) &&
					(relbox.Min.y + speed.y * dtime < ysize) &&
					(relbox.Max.y + speed.y * dtime > 0))
				return 2;
		}
		//else if(relbox.Min.z > zsize)
		//{
		//	return -1;
		//}
	}
	else if(speed.z < 0) // Check for collision with z+ plane
	{
		if(relbox.Min.z >= zsize - d)
		{
			dtime = (zsize - relbox.Min.z) / speed.z;
			if((relbox.Min.x + speed.x * dtime < xsize) &&
					(relbox.Max.x + speed.x * dtime > 0) &&
					(relbox.Min.y + speed.y * dtime < ysize) &&
					(relbox.Max.y + speed.y * dtime > 0))
				return 2;
		}
		//else if(relbox.Max.z < 0)
		//{
		//	return -1;
		//}
	}

	return -1;
}

